home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / PowerPlant / Window Utilities / UMenuedWindows.cp next >
Encoding:
Text File  |  1997-01-31  |  12.8 KB  |  401 lines  |  [TEXT/R*ch]

  1. // ===========================================================================
  2. //    File:                        UMenuedWindows.cp
  3. // Version:                    1.0 - May 7, 1996
  4. //    Author:                    Mike Shields (mshields@inconnect.com)
  5. //                            
  6. //    Copyright ©1996 Mike Shields. All rights reserved.
  7. //    I hereby grant users of UMenuedWindows permission to use it (or any modified 
  8. //    version of it) in applications (or any other type of Macintosh software 
  9. //    like extensions -- freeware, shareware, commercial, or other) for free, 
  10. //    subject to the terms that:
  11. //
  12. //        (1)  This agreement is non-exclusive.
  13. //
  14. //        (2)  I, Mike Shields, retain the copyright to the original source code.
  15. //
  16. //    These two items are the only required conditions for use. However, I do have 
  17. //    an additional request. Note, however, that this is only a request, and 
  18. //    that it is not a required condition for use of this code.
  19. //
  20. //        (1) That I be given credit for UMenuedWindows code in the copyrights or 
  21. //            acknowledgements section of your manual or other appropriate documentation.
  22. //
  23. //
  24. //    I would like to repeat that this last item is only a request. You are prefectly 
  25. //    free to choose not to do any or all of them.
  26. //    
  27. //        This source code is distributed in the hope that it will be useful,
  28. //        but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. //        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  30. // ===========================================================================
  31. //    UMenuedWindows.h        <- double-click + Command-D to see class declaration
  32. //
  33. // A set of classes which allow you to manage the dynamic portion of a Windows
  34. // menu in your application. These include the static class which does all of the
  35. // real work, an LAttachment class which manages the selection and hiliting of the
  36. // menu items, and a LWindow subclass which knows how to add and delete itself from
  37. // the menu
  38.  
  39. #include "UMenuedWindows.h"
  40.  
  41. #include <LWindow.h>
  42. #include <UWindows.h>
  43. #include <LMenu.h>
  44. #include <LMenuBar.h>
  45. #include <PP_Messages.h>
  46. #include <LString.h>
  47. #include <PP_KeyCodes.h>
  48. #include <UDesktop.h>
  49. #include <LArray.h>
  50.  
  51. #ifndef __MENUS__
  52. #include <Menus.h>
  53. #endif
  54.  
  55. ResIDT    UMenuedWindows::sMenuID = 0;
  56. Int16        UMenuedWindows::sSeparatorPosition = 0;
  57. LArray*    UMenuedWindows::sWindowList = nil;
  58.  
  59. #pragma mark === UMenuedWindows ===
  60. //---------------------------------------------------------------------------
  61. // UMenuedWindows::InitMenuedWindows
  62. //---------------------------------------------------------------------------
  63. void UMenuedWindows::InitMenuedWindows(Int16 inMENUid, LApplication* inApplication)
  64. {
  65.     SignalIf_(inApplication == nil);
  66.  
  67.     sMenuID = inMENUid;
  68.  
  69.     LMenu* theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
  70.     SignalIf_(theMenu == nil);
  71.     sSeparatorPosition = ::CountMItems(theMenu->GetMacMenuH()) + 1;
  72.     if ( sSeparatorPosition == 1 )
  73.         sSeparatorPosition = 0;
  74.     sWindowList = new LArray(sizeof(LWindow*));
  75.     
  76.     inApplication->AddAttachment(new CMenuedWindowsAttachment(sMenuID, sSeparatorPosition + 1));
  77. }
  78.  
  79. //---------------------------------------------------------------------------
  80. // UMenuedWindows::AddWindowToMenu
  81. //---------------------------------------------------------------------------
  82. void UMenuedWindows::AddWindowToMenu(LWindow* inWindow)
  83. {
  84.     SignalIf_(sWindowList == nil);
  85.     
  86.     LMenu*        theMenu;
  87.     MenuHandle    macMenuH;
  88.     Int16            menuLength;
  89.     LStr255        windowTitle;
  90.     
  91.     theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
  92.     SignalIfNot_(theMenu);
  93.  
  94.     macMenuH = theMenu->GetMacMenuH();
  95.     menuLength = ::CountMItems(macMenuH);
  96.     
  97.     // Insert separator line if neccessary
  98.     if ( (sSeparatorPosition > 0) && ((menuLength + 1) == sSeparatorPosition) ) 
  99.     {
  100.         ::InsertMenuItem(macMenuH, "\p-", ++menuLength);
  101.     }
  102.     
  103.     inWindow->GetDescriptor(windowTitle);
  104.     ::InsertMenuItem(macMenuH, "\p ", ++menuLength);
  105.     ::SetMenuItemText(macMenuH, menuLength, windowTitle);
  106.     
  107.     sWindowList->InsertItemsAt(1, LArray::index_Last, &inWindow);
  108.     
  109.     LCommander::SetUpdateCommandStatus(true);
  110. }
  111.  
  112. //---------------------------------------------------------------------------
  113. // UMenuedWindows::RemoveWindowFromMenu
  114. //---------------------------------------------------------------------------
  115. void UMenuedWindows::RemoveWindowFromMenu(LWindow* inWindow)
  116. {
  117.     SignalIf_(sWindowList == nil);
  118.     
  119.     LMenu*        theMenu;
  120.     MenuHandle    macMenuH;
  121.     Int16            menuLength;
  122.     Int16            menuIndex;
  123.     
  124.     theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
  125.     SignalIfNot_(theMenu);
  126.  
  127.     macMenuH = theMenu->GetMacMenuH();
  128.     menuLength = ::CountMItems(macMenuH);
  129.     
  130.     menuIndex = UMenuedWindows::WindowToMenuItem(inWindow);
  131.  
  132.     if ( menuIndex != LArray::index_Bad )
  133.     {
  134.         sWindowList->Remove(&inWindow);
  135.  
  136.         ::DeleteMenuItem(macMenuH, menuIndex);        
  137.         menuLength--;
  138.         
  139.         // Remove separator line if neccessary
  140.         if ( (sSeparatorPosition > 1) && (menuLength == sSeparatorPosition) ) 
  141.             ::DeleteMenuItem(macMenuH, menuLength);
  142.  
  143.         LCommander::SetUpdateCommandStatus(true);
  144.     }
  145. }
  146.  
  147. //---------------------------------------------------------------------------
  148. // UMenuedWindows::WindowToMenuItem
  149. //---------------------------------------------------------------------------
  150. Int16 UMenuedWindows::WindowToMenuItem(LWindow* inWindow)
  151. {
  152.     SignalIf_(sWindowList == nil);
  153.     
  154.     Int16            result = LArray::index_Bad;
  155.     ArrayIndexT    windowIndex;
  156.  
  157.     if ( inWindow != NULL )
  158.     {
  159.         windowIndex = sWindowList->FetchIndexOf(&inWindow);
  160.         if ( windowIndex != LArray::index_Bad )
  161.             result = windowIndex + sSeparatorPosition;
  162.         else
  163.             SignalPStr_("\pInvalid LWindow to UMenuedWindows::WindowToMenuItem");        
  164.     }
  165.     return result;
  166. }
  167.  
  168. //---------------------------------------------------------------------------
  169. // UMenuedWindows::MenuItemToWindow
  170. //---------------------------------------------------------------------------
  171. LWindow* UMenuedWindows::MenuItemToWindow(Int16 inMenuItem)
  172. {
  173.     SignalIf_(sWindowList == nil);
  174.     
  175.     LWindow*        result = nil;
  176.     Int16            listIndex = 1;
  177.     
  178.     if ( sSeparatorPosition > 0 && (inMenuItem > sSeparatorPosition) )
  179.         listIndex = inMenuItem - sSeparatorPosition;
  180.     else
  181.         listIndex = inMenuItem;
  182.  
  183.     if ( sWindowList->FetchItemAt(listIndex, &result) == false )
  184.         SignalPStr_("\pInvalid menu item to UMenuedWindows::MenuItemToWindow");    
  185.     return result;
  186. }
  187.  
  188. //---------------------------------------------------------------------------
  189. // UMenuedWindows::SetCommandKey
  190. //---------------------------------------------------------------------------
  191. void UMenuedWindows::SetCommandKey(LWindow* inWindow, char inKey)
  192. {
  193.     SignalIf_(sWindowList == nil);
  194.     
  195.     Int16                itsMenuItem;
  196.  
  197.     itsMenuItem = WindowToMenuItem(inWindow);
  198.     if ( itsMenuItem != LArray::index_Bad )
  199.     {
  200.         LMenu*    theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(sMenuID);
  201.         SignalIfNot_(theMenu);
  202.  
  203.         ::SetItemCmd(theMenu->GetMacMenuH(), itsMenuItem, inKey);
  204.     }
  205. }
  206.  
  207. //---------------------------------------------------------------------------
  208. // UMenuedWindows::GetMenuItemStatus
  209. //---------------------------------------------------------------------------
  210. void UMenuedWindows::GetMenuItemStatus(Int16 inMenuItem, Boolean &outEnabled, 
  211.                                                     Boolean &outUsesMark, Char16 &outMark, 
  212.                                                     StringPtr outName)
  213. {
  214.     SignalIf_(sWindowList == nil);
  215.     
  216.     // Set up some appropriate defaults in case something below goes wrong.
  217.     outUsesMark = true,
  218.     outMark = noMark;
  219.     
  220.     LWindow*    theWindow = MenuItemToWindow(inMenuItem);
  221.     if ( theWindow )
  222.     {
  223.         outEnabled = true;
  224.         
  225.         // if this is the top window, we want to show a check mark next to it.
  226.         if ( UDesktop::FetchTopRegular() == theWindow )
  227.             outMark = char_Lozenge;
  228.         
  229.         // We also want to update the title of the menu item to reflect 
  230.         // the current name.
  231.         LStr255 windowTitle;
  232.         theWindow->GetDescriptor(windowTitle);
  233.         
  234.         LString::CopyPStr(windowTitle, outName);
  235.     }
  236.     else
  237.     {
  238.         SignalPStr_("\pUMenuedWindows::GetMenuItemStatus: Window doesn't exist");
  239.     }
  240. }
  241.  
  242. //---------------------------------------------------------------------------
  243. // UMenuedWindows::SelectWindowMenuWindow
  244. //---------------------------------------------------------------------------
  245. void UMenuedWindows::SelectWindowMenuWindow(Int16 inMenuItem)
  246. {
  247.     SignalIf_(sWindowList == nil);
  248.     
  249.     LWindow*    theWindow = MenuItemToWindow(inMenuItem);
  250.     if ( theWindow )
  251.     {
  252.         // Bring the window to the front and make sure it's visible.
  253.         theWindow->Select();
  254.         theWindow->Show();
  255.     }
  256.     else
  257.     {
  258.         SignalPStr_("\pUMenuedWindows::SelectWindowMenuWindow: Window doesn't exist");
  259.     }
  260. }
  261.  
  262. #pragma mark === CMenuedWindowsAttachment ===
  263. //---------------------------------------------------------------------------
  264. // CMenuedWindowsAttachment::CMenuedWindowsAttachment
  265. //---------------------------------------------------------------------------
  266. CMenuedWindowsAttachment::CMenuedWindowsAttachment(ResIDT inMenuID, Int16 inFirstItem)
  267.     : LAttachment(msg_AnyMessage), mMenuID(inMenuID), mFirstItem(inFirstItem)
  268. {
  269. }
  270.  
  271. //---------------------------------------------------------------------------
  272. // CMenuedWindowsAttachment::~CMenuedWindowsAttachment
  273. //---------------------------------------------------------------------------
  274. CMenuedWindowsAttachment::~CMenuedWindowsAttachment()
  275. {
  276. }
  277.  
  278. //---------------------------------------------------------------------------
  279. // CMenuedWindowsAttachment::ExecuteSelf
  280. //---------------------------------------------------------------------------
  281. void CMenuedWindowsAttachment::ExecuteSelf(MessageT inMessage, void *ioParam)
  282. {
  283.     ResIDT    menuID;
  284.     Int16        menuItem;
  285.     
  286.     // By default we want the host to execute.
  287.     SetExecuteHost(true);
  288.     
  289.     if ( inMessage == msg_CommandStatus )
  290.     {
  291.         if ( UDesktop::FrontWindowIsModal() )
  292.         {
  293.             return;
  294.         }
  295.         
  296.         SCommandStatus* status = (SCommandStatus*)ioParam;
  297.         if ( LCommander::IsSyntheticCommand(status->command, menuID, menuItem) )
  298.         {
  299.             if ( menuID == mMenuID )
  300.             {
  301.                 LMenu*        theMenu;
  302.                 MenuHandle    macMenuH;
  303.                 Int16            menuLength;
  304.                 Boolean        usesMark;
  305.                 Char16        mark;
  306.                 Str255        name;
  307.                 
  308.                 theMenu = LMenuBar::GetCurrentMenuBar()->FetchMenu(mMenuID);
  309.                 SignalIfNot_(theMenu);
  310.                 macMenuH = theMenu->GetMacMenuH();
  311.                 menuLength = ::CountMItems(macMenuH);
  312.         
  313.                 for ( Int16 i = mFirstItem; i <= menuLength; i++ )
  314.                 {
  315.                     UMenuedWindows::GetMenuItemStatus(i, *status->enabled, 
  316.                                                             usesMark, mark, name);
  317.                     
  318.                     if ( usesMark ) 
  319.                         ::SetItemMark(macMenuH, i, mark);
  320.                     
  321.                     if ( name[0] > 0 ) 
  322.                         ::SetMenuItemText(macMenuH, i, name);
  323.                 }
  324.                 // OK, we handled this so no reason for the host to try to handle it.
  325.                 SetExecuteHost(false);
  326.             }
  327.         }
  328.     }
  329.     else if ( LCommander::IsSyntheticCommand(inMessage, menuID, menuItem) )
  330.     {
  331.         // we're being asked to respond to selecting a command. If it's in the range of our menu
  332.         // items we need to select the window.
  333.         if ( menuID == mMenuID && menuItem >= mFirstItem )
  334.         {
  335.             UMenuedWindows::SelectWindowMenuWindow(menuItem);
  336.  
  337.             // OK, we handled this so no reason for the host to try to handle it.
  338.             SetExecuteHost(false);
  339.         }
  340.     }
  341. }
  342.  
  343. #pragma mark === CMenuedWindow ===
  344. //---------------------------------------------------------------------------
  345. // CMenuedWindow::CreateWindowStream
  346. //---------------------------------------------------------------------------
  347. //    Return a newly created Window object initialized with data from a Stream
  348. CMenuedWindow* CMenuedWindow::CreateFromStream(LStream *inStream)
  349. {
  350.     return (new CMenuedWindow(inStream));
  351. }
  352.  
  353. //---------------------------------------------------------------------------
  354. // CMenuedWindow::CMenuedWindow
  355. //---------------------------------------------------------------------------
  356. //    Default Constructor
  357. CMenuedWindow::CMenuedWindow()
  358. {
  359. }
  360.  
  361. //---------------------------------------------------------------------------
  362. // CMenuedWindow::CMenuedWindow(SWindowInfo&)
  363. //---------------------------------------------------------------------------
  364. //    Construct Window from the data in a struct
  365. CMenuedWindow::CMenuedWindow(const SWindowInfo &inWindowInfo)
  366.     : LWindow(inWindowInfo)
  367. {
  368.     UMenuedWindows::AddWindowToMenu(this);
  369. }
  370.  
  371. //---------------------------------------------------------------------------
  372. // CMenuedWindow::CMenuedWindow(ResIDT, Uint32, LCommander*)
  373. //---------------------------------------------------------------------------
  374. //    Construct a Window from a WIND Resource with the specified attributes
  375. //    and SuperCommander
  376. CMenuedWindow::CMenuedWindow(ResIDT inWINDid, Uint32 inAttributes, LCommander *inSuper)
  377.         : LWindow(inWINDid, inAttributes, inSuper)
  378. {
  379.     UMenuedWindows::AddWindowToMenu(this);
  380. }
  381.  
  382. //---------------------------------------------------------------------------
  383. // CMenuedWindow::CMenuedWindow(LStream*)
  384. //---------------------------------------------------------------------------
  385. //    Construct Window from the data in a stream
  386. CMenuedWindow::CMenuedWindow(LStream *inStream)
  387.     : LWindow(inStream)
  388. {
  389.     UMenuedWindows::AddWindowToMenu(this);
  390. }
  391.  
  392. //---------------------------------------------------------------------------
  393. // CMenuedWindow::~CMenuedWindow
  394. //---------------------------------------------------------------------------
  395. //    Destructor
  396. CMenuedWindow::~CMenuedWindow()
  397. {
  398.     UMenuedWindows::RemoveWindowFromMenu(this);
  399. }
  400.  
  401.